package fr.univsavoie.tatiana2dvisualisation;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.XYLayout;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;

import fr.emse.tatiana.replayable.IReplayableModel;

public class EyeTrackerModelPart extends AbstractGraphicalEditPart {

	private List<DrawCondition> conditions;
	private long begin = -1000;
	private long end = -1000;
    private long current = -1000; 
	private Set<EyeTrackerEvent> childrenset = new HashSet<EyeTrackerEvent>();
	private List<EyeTrackerReplayableEvent> replayableproxy = new Vector<EyeTrackerReplayableEvent>();
	
	public EyeTrackerModelPart(IReplayableModel model,
			List<DrawCondition> conditions) {
		super();
		setModel(model);
		int xcol = model.getFacetCol("x");
		int ycol = model.getFacetCol("y");	
		int pressurecol = model.getFacetCol("p");
		int typecol = model.getFacetCol("type");
		Integer minx = null;
		Integer maxx = null;
		Integer miny = null;
		Integer maxy = null;
		for (int i=0; i<model.getEventCount(); i++) {
			Object event = model.getEvent(i);
			int x = Integer.parseInt(model.getFacetText(event, xcol));
			int y = Integer.parseInt(model.getFacetText(event, ycol));
			int p = -1;
			try {
				p = Integer.parseInt(model.getFacetText(event, pressurecol));
			} catch (NumberFormatException nfe) {
				//doesn't matter
			}
			String type = model.getFacetText(event, typecol);
			if (type.equals("pen")) { //TODO
				if ((minx==null || x<minx) && x!=0) {
					minx=x;
				}
				if (maxx==null || x>maxx) {
					maxx=x;
				}
				if ((miny==null || y<miny) && y!=0) {
					miny=y;
				}
				if (maxy==null || y>maxy) {
					maxy=y;
				}
			}
			Long time = model.getBeginTime(event);
			replayableproxy.add(new EyeTrackerReplayableEvent(x,y,p,i,time,type));
		}
		this.conditions = conditions;
		for (DrawCondition dc: conditions) {
			dc.setBounds(minx,maxx,miny,maxy);
		}
	}
	
	private void updateModelChildrenSet() {
		childrenset = new HashSet<EyeTrackerEvent>();
		Map<DrawCondition,EyeTrackerReplayableEvent> prevs = new HashMap<DrawCondition, EyeTrackerReplayableEvent>();
		

		for (int i=0, ii=replayableproxy.size(); i<ii; i++) {
			EyeTrackerReplayableEvent event = replayableproxy.get(i);
			for (DrawCondition dc : conditions) {
				EyeTrackerReplayableEvent prev = prevs.get(dc);
				if (prev != null ) {
					if (dc.willDraw(event, prev, getTimeType(event))) {
						childrenset.add(new EyeTrackerEvent(prev,event,getTimeType(event), dc));
					}
				}
				if (dc.meetsCondition(event))
					prevs.put(dc, event);
			}
		}
	}
	
	@Override
	protected List<EyeTrackerEvent> getModelChildren() {
		updateModelChildrenSet();
		return new Vector<EyeTrackerEvent>(childrenset);
	}
	
	int getTimeType(EyeTrackerReplayableEvent event) {
		int type = DrawCondition.CURRENT;
		if (event.time<(current+20) && event.time>(current-20)) {
			type = DrawCondition.PRESENT;
		} else if (event.time<begin) {
			type = DrawCondition.PAST;
		} else if (event.time>end) {
			type = DrawCondition.FUTURE;
		} 
		return type;
	}

	@Override
	protected IFigure createFigure() {
		IFigure ret = new Figure();
		XYLayout contentsLayout = new XYLayout();
		ret.setLayoutManager(contentsLayout);
		return ret;
	}

	@Override
	protected void createEditPolicies() {
		installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, null);

	}

	public void setCurrentTime(long begin, long end, long current) {
		this.begin = begin;
		this.end = end;
		this.current = current;
		Set<EyeTrackerEvent> toremove=childrenset;
		updateModelChildrenSet();
		Set<EyeTrackerEvent> toadd = new HashSet<EyeTrackerEvent>(childrenset);
		toadd.removeAll(toremove);
		toremove.removeAll(childrenset);
		for (EyeTrackerEvent ete: toremove) {
			
			removeChild(getViewer().getEditPartFactory().createEditPart(this, ete));
		}

		for (EyeTrackerEvent ete: toadd) {
			addChild(getViewer().getEditPartFactory().createEditPart(this, ete),0);
			
		}
	}

}
